home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / jade / src / x11_eventloop.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  7KB  |  304 lines

  1. /* x11_eventloop.c -- Eventloop for X11
  2.    Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
  3.  
  4.    This file is part of Jade.
  5.  
  6.    Jade is free software; you can redistribute it and/or modify it
  7.    under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    Jade is distributed in the hope that it will be useful, but
  12.    WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with Jade; see the file COPYING.  If not, write to
  18.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "jade.h"
  21. #include "jade_protos.h"
  22.  
  23. #ifdef HAVE_UNIX
  24. # include <sys/types.h>
  25. # include <sys/time.h>
  26. # include <errno.h>
  27. #else
  28.   you lose
  29. #endif
  30.  
  31. _PR VALUE event_loop(void);
  32.  
  33. static VALUE
  34. handle_event(XEvent *xev)
  35. {
  36.     VW *oldvw = curr_vw, *ev_vw;
  37.     VALUE result = sym_nil;
  38. /*  std_message(curr_vw); */
  39.     ev_vw = x11_find_window_view(xev->xany.window);
  40.     if(ev_vw)
  41.     {
  42.     switch(xev->type)
  43.     {
  44.         u_long code, mods;
  45.     case MappingNotify:
  46.         XRefreshKeyboardMapping(&xev->xmapping);
  47.         break;
  48.     case Expose:
  49.         if(ev_vw->vw_Flags & VWFF_SLEEPING)
  50.         {
  51.         /* Guess that the wm uniconified us? */
  52.         ev_vw->vw_Flags &= ~VWFF_SLEEPING;
  53.         }
  54.         if(ev_vw->vw_Flags & VWFF_FORCE_REFRESH)
  55.         {
  56.         /* Wait until the last Expose then do a total redraw.  */
  57.         if(xev->xexpose.count == 0)
  58.         {
  59.             draw_message_line(ev_vw);
  60.             ev_vw->vw_Flags |= VWFF_REFRESH_STATUS;
  61.             refresh_window(ev_vw);
  62.         }
  63.         }
  64.         else
  65.         x11_handle_expose(ev_vw, &xev->xexpose);
  66.         if(ev_vw == oldvw)
  67.         cursor(ev_vw, CURS_ON);
  68.         break;
  69.     case ConfigureNotify:
  70.         if((ev_vw->vw_WindowSys.ws_Width != xev->xconfigure.width)
  71.            || (ev_vw->vw_WindowSys.ws_Height != xev->xconfigure.height))
  72.         {
  73.         if(ev_vw == oldvw)
  74.             cursor(ev_vw, CURS_OFF);
  75.         if((ev_vw->vw_WindowSys.ws_Height != 0)
  76.            && (ev_vw->vw_WindowSys.ws_Height < xev->xconfigure.height))
  77.         {
  78.             /* Have to clear out the status line. It can be left in
  79.                the wrong place.     */
  80.             CLR_AREA(ev_vw, 0, ev_vw->vw_MessageLineY,
  81.                  ev_vw->vw_WindowSys.ws_Width, ev_vw->vw_FontY+2);
  82.         }
  83.         ev_vw->vw_WindowSys.ws_Width = xev->xconfigure.width;
  84.         ev_vw->vw_WindowSys.ws_Height = xev->xconfigure.height;
  85.         x11_update_dimensions(ev_vw, xev->xconfigure.width, xev->xconfigure.height);
  86.         if(ev_vw == oldvw)
  87.             cursor(ev_vw, CURS_ON);
  88.         }
  89.         break;
  90.     case ClientMessage:
  91.         if((xev->xclient.format == 32)
  92.         && (xev->xclient.data.l[0] == x11_wm_del_win))
  93.         {
  94.         curr_vw = ev_vw;
  95.         if(ev_vw != oldvw)
  96.         {
  97.             /* Window switch */
  98.             undo_distinct();
  99.             cursor(oldvw, CURS_OFF);
  100.         }
  101.         else
  102.             cursor(ev_vw, CURS_OFF);
  103.         result = cmd_eval_hook2(MKSTR("window-closed-hook"), sym_nil);
  104.         if(curr_vw)
  105.         {
  106.             refresh_world();
  107.             cursor(curr_vw, CURS_ON);
  108.         }
  109.         }
  110.         break;
  111.     case FocusIn:
  112.         if(ev_vw != oldvw)
  113.         {
  114.         cursor(oldvw, CURS_OFF);
  115.         cursor(ev_vw, CURS_ON);
  116.         curr_vw = ev_vw;
  117.         undo_distinct();
  118.         }
  119.         break;
  120.     case ButtonPress:
  121.     case ButtonRelease:
  122.     case KeyPress:
  123.         code = mods = 0;
  124.         translate_event(&code, &mods, xev);
  125.         if(mods & EV_TYPE_MASK)
  126.         {
  127.         curr_vw = ev_vw;
  128.         if(oldvw != ev_vw)
  129.         {
  130.             cursor(oldvw, CURS_OFF);
  131.             undo_distinct();
  132.         }
  133.         result = usekey(xev, code, mods, (ev_vw == oldvw));
  134.         }
  135.         break;
  136.     }
  137.     }
  138.     return(result);
  139. }
  140.  
  141. VALUE
  142. event_loop(void)
  143. {
  144.     VALUE result = sym_nil;
  145.     recurse_depth++;
  146.     std_message(curr_vw);
  147.     refresh_world_curs();
  148.     while(curr_vw)
  149.     {
  150. #ifdef HAVE_UNIX
  151.     fd_set copy;
  152.     struct timeval timeout;
  153.     int number, i;
  154.     bool refreshp;
  155. #endif
  156.     /*
  157.      * HERE... Read out all events in Q
  158.      */
  159.     while(INT_P || XEventsQueued(x11_display, QueuedAfterReading) > 0)
  160.     {
  161.         if(INT_P)
  162.         result = NULL;
  163.         else
  164.         {
  165.         XEvent ev;
  166.         XNextEvent(x11_display, &ev);
  167.         result = handle_event(&ev);
  168.         }
  169.         if(!result)
  170.         {
  171.         if(throw_value)
  172.         {
  173.             VALUE tv = throw_value;
  174.             VALUE car = VCAR(tv);
  175.             throw_value = NULL;
  176.             if(car == sym_exit)
  177.             {
  178.             result = VCDR(tv);
  179.             if(recurse_depth > 0)
  180.                 goto end;
  181.             }
  182.             else if((car == sym_top_level) && (recurse_depth == 0))
  183.             result = VCDR(tv);
  184.             else if(car == sym_quit)
  185.             goto end;
  186.             else if(car == sym_user_interrupt)
  187.             {
  188.             handle_error(car, sym_nil);
  189.             result = sym_nil;
  190.             }
  191.             else if(car == sym_error)
  192.             {
  193.             handle_error(VCAR(VCDR(tv)), VCDR(VCDR(tv)));
  194.             result = sym_nil;
  195.             }
  196.             else if(recurse_depth == 0)
  197.             {
  198.             result = sym_nil;
  199.             handle_error(sym_no_catcher, LIST_1(car));
  200.             }
  201.             else
  202.             {
  203.             throw_value = tv;
  204.             goto end;
  205.             }
  206.         }
  207.         else
  208.             result = sym_nil;
  209.         }
  210.         if(!curr_vw)
  211.         goto end;
  212. #if 0
  213.         std_message(curr_vw);
  214.         if(curr_vw->vw_Flags & VWFF_REFRESH_STATUS)
  215.         {
  216.         refresh_message(curr_vw);
  217.         curr_vw->vw_Flags &= ~VWFF_REFRESH_STATUS;
  218.         }
  219. #endif
  220.     }
  221.  
  222. # ifdef HAVE_SUBPROCESSES
  223.     if(proc_notification())
  224.     {
  225.         std_message(curr_vw);
  226.         refresh_world_curs();
  227.     }
  228. # endif
  229.  
  230.     XFlush(x11_display);
  231.  
  232. #ifdef HAVE_UNIX
  233.     copy = x11_fd_read_set;
  234.     timeout.tv_sec = EVENT_TIMEOUT_LENGTH;
  235.     timeout.tv_usec = 0;
  236.     /* Don't want select() to restart after a SIGCHLD; there may be
  237.        a notification to dispatch.  */
  238. # ifdef HAVE_SUBPROCESSES
  239.     sigchld_restart(FALSE);
  240. # endif
  241.     number = select(FD_SETSIZE, ©, NULL, NULL, &timeout);
  242. # ifdef HAVE_SUBPROCESSES
  243.     sigchld_restart(TRUE);
  244. # endif
  245.     refreshp = FALSE;
  246.     if(number > 0)
  247.     {
  248.         /*
  249.          * no need to test first 3 descriptors
  250.          */
  251.         i = 3;
  252.         while(number > 0)
  253.         {
  254.         if(FD_ISSET(i, ©))
  255.         {
  256.             number--;
  257.             if(x11_fd_read_action[i])
  258.             {
  259.             x11_fd_read_action[i](i);
  260.             refreshp = TRUE;
  261.             }
  262.         }
  263.         i++;
  264.         }
  265.     }
  266.     else if(number == 0)
  267.     {
  268.         /* A timeout; do one of:
  269.          Print the current key-prefix
  270.          Auto-save a buffer
  271.          GC if enough data allocated
  272.          Run the `idle-hook'  */
  273.         if(print_event_prefix() || auto_save_buffers())
  274.         refreshp = TRUE;
  275.         else if(data_after_gc > idle_gc_threshold)
  276.         {
  277.         /* nothing was saved so try a GC */
  278.         cmd_garbage_collect(sym_t);
  279.         }
  280.         else
  281.         {
  282.         VALUE hook = cmd_symbol_value(sym_idle_hook, sym_t);
  283.         if(!VOIDP(hook) && !NILP(hook))
  284.         {
  285.             cmd_eval_hook2(sym_idle_hook, sym_nil);
  286.             refreshp = TRUE;
  287.         }
  288.         }
  289.     }
  290. #else
  291.     whatever you like...
  292. #endif /* HAVE_UNIX */
  293.  
  294.     if(refreshp)
  295.     {
  296.         std_message(curr_vw);
  297.         refresh_world_curs();
  298.     }
  299.     }
  300. end:
  301.     recurse_depth--;
  302.     return(result);
  303. }
  304.